<?php
/** 分类Code换算
 * @version ZhangXiLian 2014-08-29 */
class CategoryCodeUtil {
	public static $dMask = array (
			'5' => 255,
			'4' => 16128,
			'3' => 1032192,
			'2' => 66060288,
			'1' => 4227858432 
	);
	public static $dOffside = array (
			'5' => 1,
			'4' => 256,
			'3' => 16384,
			'2' => 1048576,
			'1' => 67108864
	);
// 	public static $cateLevelMap = array (
// 			'5' => '/level5',
// 			'4' => '/level4',
// 			'3' => '/level3',
// 			'2' => '/level2',
// 			'1' => '/level1' 
// 	);
// 	public static $segment = array (
// 			'1' => 4227858432,
// 			'2' => 4293918720,
// 			'3' => 4294950912,
// 			'4' => 4294967040,
// 			'5' => 4294967295 
// 	);
	/** 根据code获取等级名称 */
	public static function getCategoryLevel($dCategoryCode) {
		$dCategoryCode = floatval ( $dCategoryCode );
		if ('0' == $dCategoryCode) {
			return '0';
		}
		
		$dRes = $dCategoryCode & CategoryCodeUtil::$dMask ['5'];
		if ($dRes != 0) {
			return '5';
		}
		$dRes = $dCategoryCode & CategoryCodeUtil::$dMask ['4'];
		if ($dRes != 0) {
			return '4';
		}
		$dRes = $dCategoryCode & CategoryCodeUtil::$dMask ['3'];
		if ($dRes != 0) {
			return '3';
		}
		
		$dRes = $dCategoryCode & CategoryCodeUtil::$dMask ['2'];
		if ($dRes != 0) {
			return '2';
		}
		return '1';
	}
	/** 根据code获取全称 */
	public static function getFullPath($CategoryCode) {
		$codeList = CategoryCodeUtil::getCategoryCodeArray ( $CategoryCode );
		$strKey = '';
		for($i = 0; $i < count ( $codeList ); $i ++) {
			$strKey = $strKey . '/C' . $codeList [$i];
		}
		return $strKey;
	}
	/** 根据code获取下级范围 */
	public static function getCategoryCodeRange($CategoryCode) {
		if (empty ( $CategoryCode )) {
			return;
		}
		$type = CategoryCodeUtil::getCategoryLevel ( $CategoryCode );
		if ($type == '5') {
			$dRange ['first'] = $CategoryCode;
			$dRange ['last'] = $CategoryCode;
		} else {
			$dRange ['first'] = $CategoryCode;
			if ($type == '4') {
				$dRange ['last'] = $CategoryCode + CategoryCodeUtil::$dMask ['5'];
			} else {
				if ($type == '3') {
					$dRange ['last'] = $CategoryCode + CategoryCodeUtil::$dMask ['4'] + CategoryCodeUtil::$dMask ['5'];
				} else {
					if ($type == '2') {
						$dRange ['last'] = $CategoryCode + CategoryCodeUtil::$dMask ['3'] + CategoryCodeUtil::$dMask ['4'] + CategoryCodeUtil::$dMask ['5'];
					} else {
						$dRange ['last'] = $CategoryCode + + CategoryCodeUtil::$dMask ['5'] + CategoryCodeUtil::$dMask ['4'] + CategoryCodeUtil::$dMask ['3'] + CategoryCodeUtil::$dMask ['2'];
					}
				}
			}
		}
		return $dRange;
	}
	
	private static function shuffleBits($v, $bits) {
		$sgnMax = ( float ) 2147483648; // 2^31
		
		if ($v > $sgnMax) {
			$tmp = $v - $sgnMax;
			$tmp >>= $bits;
			$tmp <<= $bits;
			$v = $tmp + $sgnMax;
		} else {
			$v >>= $bits;
			$v <<= $bits;
		}
		
		return $v;
	}
	
	public static function getCategoryCodeArray($code) {
		$codeList = array ();
		$level = ( int ) CategoryCodeUtil::getCategoryLevel ( $code );
		for($i = 1; $i < $level; $i ++) {
			if (1 === $i) {
				$c = self::shuffleBits ( $code, 26 );
				$codeList [] = $c;
			} else if (2 === $i) {
				$c = self::shuffleBits ( $code, 20 );
				$codeList [] = $c;
			} else if (3 === $i) {
				$c = self::shuffleBits ( $code, 14 );
				$codeList [] = $c;
			} else if (4 === $i) {
				$c = self::shuffleBits ( $code, 8 );
				$codeList [] = $c;
			}
		}
		
		$codeList [] = $code;
		return $codeList;
	}
		
	// $step = 0 : calculate the same level next code
	// $step > 1 :calculate the next $step level next code
	public static function calNextCategoryCode($preCode, $step) {
		$level = CategoryCodeUtil::getCategoryLevel ( $preCode );
		$n = ( int ) $level + $step;
		$nextCode = $preCode + CategoryCodeUtil::$dOffside ["{$n}"];
		return $nextCode;
	}	
	
}

?>
